
using System;
using System.IO;
using System.Security.Cryptography;


namespace SharpCart.Utils.Security
{
	/// <summary>
	/// This class handles basic encryption tasks, such as hashing, file encryption/decryption, and string encryption/decryption.
	/// </summary>
	public class Encryption
	{

        public static string HashPassword(string Password, int Nonce)
        {
            Nonce = Math.Abs(Nonce);
            for (int i = 0; i < Nonce; i++)
            {
                Password += Nonce.ToString();
                Password = HashString(Password);
            }
            return Password;
        }

		/// <summary>
		/// Hash a string using a SHA256 hash
		/// </summary>
		/// <param Name="StringToHash">The string to be hashed</param>
		/// <returns>The hashed string</returns>
		public static string HashString(string StringToHash)
		{
			System.Security.Cryptography.SHA256Managed hash = new SHA256Managed();
			byte[] byt_hash = hash.ComputeHash(System.Text.Encoding.Unicode.GetBytes(StringToHash));
			string str_return = "";
			foreach(byte obj_byte in byt_hash)
			{
				str_return += String.Format("{0:x2}", obj_byte);
			}
			return str_return;
		}

		/// <summary>
		/// Encrypt a byte array using the Rijndael algorithm.
		/// </summary>
		/// <param Name="ClearData"></param>
		/// <param Name="Key">The Encryption Key to use for the operation</param>
		/// <param Name="IV">The Encryption IV to use for the operation</param>
		/// <returns>The encrypted byte array</returns>
		public static byte[] Encrypt(byte[] ClearData, byte[]Key, byte[]IV)
		{
			MemoryStream ms = new MemoryStream();
			Rijndael alg = Rijndael.Create();
			alg.Key = Key; 
			alg.IV = IV; 

			CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write); 
			cs.Write(ClearData, 0, ClearData.Length); 
			cs.Close();  
			byte[] encryptedData = ms.ToArray();

			return encryptedData; 
		}

		/// <summary>
		/// Encrypt a string using the Rijndael algorithm .
		/// </summary>
		/// <param Name="ClearText"></param>
		/// <param Name="Key">The Encryption Key to use for the operation</param>
		/// <param Name="IV">The Encryption IV to use for the operation</param>
		/// <returns></returns>
		public static string Encrypt(string ClearText, byte[]Key, byte[]IV)
		{
			byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(ClearText); 
			byte[] encryptedData = Encrypt(clearBytes, Key,IV); 
			return Convert.ToBase64String(encryptedData); 
		}

		/// <summary>
		/// Decrypt a byte array using the Rijndael algorithm.
		/// </summary>
		/// <param Name="CipherBytes"></param>
		/// <param Name="Key">The Encryption Key to use for the operation</param>
		/// <param Name="IV">The Encryption IV to use for the operation</param>
		/// <returns></returns>
		public static byte[] Decrypt(byte[] CipherBytes, byte[]Key, byte[]IV)
		{
            RijndaelManaged alg = (RijndaelManaged)RijndaelManaged.Create();
			ICryptoTransform Decryptor = alg.CreateDecryptor(Key, IV);
			MemoryStream  memoryStream = new MemoryStream(CipherBytes);
			CryptoStream  cryptoStream = new CryptoStream(memoryStream, Decryptor, CryptoStreamMode.Read);
			byte[] PlainBytes = new byte[CipherBytes.Length];
			int DecryptedCount = cryptoStream.Read(PlainBytes, 0, PlainBytes.Length);
            byte[] Result = new byte[DecryptedCount];
            for (int i = 0; i < DecryptedCount; i++)
            {
                Result[i] = PlainBytes[i];
            }
			memoryStream.Close();
			cryptoStream.Close();
            return Result;
		}

		/// <summary>
		/// Decrypt a string using the Rijndael algorithm and the system Key and IV.
		/// </summary>
		/// <param Name="CipherText"></param>
		/// <param Name="Key">The Encryption Key to use for the operation</param>
		/// <param Name="IV">The Encryption IV to use for the operation</param>
		/// <returns></returns>
		public static string Decrypt(string CipherText, byte[]Key, byte[]IV)
		{
			string DecryptedData = System.Text.Encoding.Unicode.GetString(Decrypt(Convert.FromBase64String(CipherText), Key, IV));
			return DecryptedData;
		}
	}
}
